#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include "public.h"

/* Table of CRC values for high-order byte */
static const INT8U table_crc_hi[] = {
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
    0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
    0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
    0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
    0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
    0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
    0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
    0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
    0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
    0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40};

/* Table of CRC values for low-order byte */
static const INT8U table_crc_lo[] = {
    0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06,
    0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD,
    0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
    0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,
    0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4,
    0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
    0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,
    0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,
    0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
    0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29,
    0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED,
    0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
    0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60,
    0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67,
    0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
    0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,
    0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E,
    0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
    0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71,
    0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,
    0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
    0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B,
    0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B,
    0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
    0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,
    0x43, 0x83, 0x41, 0x81, 0x80, 0x40};
char get_jxOidValue(INT32U oid, INT8U *value)
{
    int i;

    for (i = 0; i < g_jxTabLen; i++)
    {
        if (oid == g_jxDevDataTab[i].oid)
        {
            if (g_jxDevDataTab[i].oidLen <= 9)
            {
                memcpy(value, &g_jxDevDataTab[i].devValInt, g_jxDevDataTab[i].oidLen - 5);
            }
            else
            {
                int idx = g_jxDevDataTab[i].longDataAtListAddr;
                memcpy(value, &g_jxDevLongDataList[idx], g_jxDevDataTab[i].oidLen - 5);
            }
            return 1;
        }
    }
    return 0;
}
char set_jxDevDataValue(INT8U *buff,int len)
{
    int i;
    char *ptr;
    int oidLen = 0;
    lWord4Byte oid;
    ptr = buff;
    int rt=1;
    lWord4Byte value;
    char sql[128];

    for (i = 0; i < len; i += oidLen)
    {
        oidLen = *ptr++;
        if(oidLen<6)return 0;
        oid.byte[0] =*ptr++;
        oid.byte[1] =*ptr++;
        oid.byte[2] =*ptr++;
        oid.byte[3] =*ptr++;
        if(oidLen <=9)
        {
            // DebugPrint("set_jxDevDataValue:oid=%d value[0]=%x\n", oid.lword,value);
            if(!set_jxOidValue(oid.lword,ptr))rt=0;
            else
            {
                value.lword=0;
                if(oidLen>=6)value.byte[0] =*ptr++;
                if(oidLen>=7)value.byte[1] =*ptr++;
                if(oidLen>=8)value.byte[2] =*ptr++;
                if(oidLen>=9)value.byte[3] =*ptr++;
                memset(sql, '\0', 128);
                sprintf(sql, "update jxDevData set valueInt = %d where oid=%d", value.lword,oid.lword);
                sql_general_set_interface(sql);
                // DebugPrint("sql=%s\n", sql);
            }
        }
    }
    for (i = 0; i < 6; i++)
    {
        g_mbSetPakcetList[i].setErrCnt=0;
    }
    return rt;
}
int get_jxDevAllRealData(INT8U *buff)
{
    int i;
    char *ptr;
    int len = 0;

    ptr = buff;
    for (i = 0; i < g_jxTabLen; i++)
    {
        if(g_jxDevDataTab[i].oidLen>255)continue;
        *ptr++ = g_jxDevDataTab[i].oidLen;
        *ptr++ = g_jxDevDataTab[i].oid;
        *ptr++ = g_jxDevDataTab[i].oid >> 8;
        *ptr++ = g_jxDevDataTab[i].oid >> 16;
        *ptr++ = g_jxDevDataTab[i].oid >> 24;

        if (g_jxDevDataTab[i].oidLen <= 9)
        {
            memcpy(ptr, &g_jxDevDataTab[i].devValInt, g_jxDevDataTab[i].oidLen - 5);
            DebugPrint("\n oid=%d value=%d",g_jxDevDataTab[i].oid,g_jxDevDataTab[i].devValInt);
       }
        else
        {
            int idx = g_jxDevDataTab[i].longDataAtListAddr;
            memcpy(ptr, &g_jxDevLongDataList[idx], g_jxDevDataTab[i].oidLen - 5);
        }
        ptr += g_jxDevDataTab[i].oidLen - 5;
        len += g_jxDevDataTab[i].oidLen;
    }
    return len;
}
char set_jxOidValue(INT32U oid, INT8U *value)
{
    int i;

    for (i = 0; i < g_jxTabLen; i++)
    {
        if (oid == g_jxDevDataTab[i].oid)
        {
            if (g_jxDevDataTab[i].oidLen <= 9)
            {
                memcpy(&g_jxDevDataTab[i].devValInt, value, g_jxDevDataTab[i].oidLen - 5);
            }
            else
            {
                int idx = g_jxDevDataTab[i].longDataAtListAddr;
                memcpy(&g_jxDevLongDataList[idx], value, g_jxDevDataTab[i].oidLen - 5);
            }
            return 1;
        }
    }
    return 0;
}
char set_mbOidDevValue(INT32U oid, INT8U *value)
{
    int i;

    for (i = 0; i < g_mbPollTabLen; i++)
    {
        if (oid == g_mbPollTab[i].oid)
        {
            if (g_mbPollTab[i].len <= 4)
            {
                memcpy(&g_mbPollTab[i].devValue, value, g_mbPollTab[i].len);
            }
            else
            {
                int idx = g_mbPollTab[i].mbLongDataAtListStartAddr;
                memcpy(&g_mbPollTab[idx], value, g_mbPollTab[i].len);
            }
            return 1;
        }
    }
    return 0;
}
int get_jxOidIdx(INT32U oid)
{
    int i;
    for (i = 0; i < g_jxTabLen; i++)
    {
        if (g_jxDevDataTab[i].oid == oid)
            return i;
    }
    return -1;
}
int get_jxOidParaType(INT32U oid)
{
    int i;
    for (i = 0; i < g_jxTabLen; i++)
    {
        if (g_jxDevDataTab[i].oid == oid)
            return g_jxDevDataTab[i].paraType;
    }
    return -1;
}
int get_jxOidParaLen(INT32U oid)
{
    int i;
    for (i = 0; i < g_jxTabLen; i++)
    {
        if (g_jxDevDataTab[i].oid == oid)
            return g_jxDevDataTab[i].oidLen;
    }
    return -1;
}

INT32U crc32_table[256];

void make_crc32_table(void)
{
    INT32U c;
    INT32U i = 0;
    int bit = 0;

    for (i = 0; i < 256; i++)
    {
        c = (INT32U)i;

        for (bit = 0; bit < 8; bit++)
        {
            if (c & 1)
            {
                c = (c >> 1) ^ (0xEDB88320);
            }
            else
            {
                c = c >> 1;
            }
        }
        crc32_table[i] = c;
    }
}

INT32U make_crc(INT32U crc, unsigned char *string, INT32U size)
{

    while (size--)
        crc = (crc >> 8) ^ (crc32_table[(crc ^ *string++) & 0xff]);

    return crc;
}
INT32U caculate_crc(unsigned char *string, INT32U size)
{
    INT32U crc = 0xFFFFFFFF;
    make_crc32_table();
    return make_crc(crc, string, size);
}

void testCrc32(void)
{
    //    int i;
    FILE *sp = NULL;
    //    FILE *dp = NULL;
    INT32U count;
    INT32U crc = 0xFFFFFFFF;
    // INT32U crc = 0;
    unsigned char buf[1024];

     make_crc32_table();

    sp = fopen("/home/ryan/share2win/jxdh01-v02.db", "rb");
    if (sp == NULL)
    {
        DebugPrint("open file error\n");
        return;
    }

    if (sp)
    {
        while (!feof(sp))
        {
            memset(buf, 0, sizeof(buf));
            count = fread(buf, 1, sizeof(buf), sp);
            crc = make_crc(crc, buf, count);
        }
    }

    DebugPrint("calculate crc is 0x%x\n", crc);
    // printf("calculate crc is %d\n", crc);
    fclose(sp);
}

const char *base64char = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

char *base64_encode(const unsigned char *bindata, char *base64, int binlength)
{
    int i, j;
    unsigned char current;

    for (i = 0, j = 0; i < binlength; i += 3)
    {
        current = (bindata[i] >> 2);
        current &= (unsigned char)0x3F;
        base64[j++] = base64char[(int)current];

        current = ((unsigned char)(bindata[i] << 4)) & ((unsigned char)0x30);
        if (i + 1 >= binlength)
        {
            base64[j++] = base64char[(int)current];
            base64[j++] = '=';
            base64[j++] = '=';
            break;
        }
        current |= ((unsigned char)(bindata[i + 1] >> 4)) & ((unsigned char)0x0F);
        base64[j++] = base64char[(int)current];

        current = ((unsigned char)(bindata[i + 1] << 2)) & ((unsigned char)0x3C);
        if (i + 2 >= binlength)
        {
            base64[j++] = base64char[(int)current];
            base64[j++] = '=';
            break;
        }
        current |= ((unsigned char)(bindata[i + 2] >> 6)) & ((unsigned char)0x03);
        base64[j++] = base64char[(int)current];

        current = ((unsigned char)bindata[i + 2]) & ((unsigned char)0x3F);
        base64[j++] = base64char[(int)current];
    }
    base64[j] = '\0';
    return base64;
}

int base64_decode(const char *base64, unsigned char *bindata)
{
    int i, j;
    unsigned char k;
    unsigned char temp[4];
    for (i = 0, j = 0; base64[i] != '\0'; i += 4)
    {
        memset(temp, 0xFF, sizeof(temp));
        for (k = 0; k < 64; k++)
        {
            if (base64char[k] == base64[i])
                temp[0] = k;
        }
        for (k = 0; k < 64; k++)
        {
            if (base64char[k] == base64[i + 1])
                temp[1] = k;
        }
        for (k = 0; k < 64; k++)
        {
            if (base64char[k] == base64[i + 2])
                temp[2] = k;
        }
        for (k = 0; k < 64; k++)
        {
            if (base64char[k] == base64[i + 3])
                temp[3] = k;
        }

        bindata[j++] = ((unsigned char)(((unsigned char)(temp[0] << 2)) & 0xFC)) |
                       ((unsigned char)((unsigned char)(temp[1] >> 4) & 0x03));
        if (base64[i + 2] == '=')
            break;

        bindata[j++] = ((unsigned char)(((unsigned char)(temp[1] << 4)) & 0xF0)) |
                       ((unsigned char)((unsigned char)(temp[2] >> 2) & 0x0F));
        if (base64[i + 3] == '=')
            break;

        bindata[j++] = ((unsigned char)(((unsigned char)(temp[2] << 6)) & 0xF0)) |
                       ((unsigned char)(temp[3] & 0x3F));
    }
    return j;
}
void HexToStr(INT8U *pbDest, INT8U *pbSrc, INT16U nLen)
{
    INT8U ddl, ddh;
    INT16U i;

    for (i = 0; i < nLen; i++)
    {
        ddh = 48 + pbSrc[i] / 16;
        ddl = 48 + pbSrc[i] % 16;
        if (ddh > 57)
            ddh = ddh + 7;
        if (ddl > 57)
            ddl = ddl + 7;
        pbDest[i * 2] = ddh;
        pbDest[i * 2 + 1] = ddl;
    }

    pbDest[nLen * 2] = '\0';
}
void StrToHex(INT8U *pbDest, INT8U *pbSrc, INT16U nLen)
{
    INT8U h1, h2;
    INT8U s1, s2;
    INT16U i;

    for (i = 0; i < nLen; i++)
    {
        h1 = pbSrc[2 * i];
        h2 = pbSrc[2 * i + 1];
        s1 = toupper(h1) - 0x30;
        if (s1 > 9)
            s1 -= 7;
        s2 = toupper(h2) - 0x30;
        if (s2 > 9)
            s2 -= 7;
        pbDest[i] = s1 * 16 + s2;
    }
}
void rmZfFun(INT8U *p, INT8U ch)
{
    INT8U i, j;

    for (i = 0; p[i] != '\0'; i++)
    {
        if (p[i] == ch)
        {
            for (j = i; p[j] != '\0'; j++)
                p[j] = p[j + 1];
        }
        if (i > 250)
            break;
    }
}

INT16U modbusCrc16(INT8U *buffer, INT16U buffer_length)
{
    INT8U crc_hi = 0xFF; /* high CRC byte initialized */
    INT8U crc_lo = 0xFF; /* low CRC byte initialized */
    INT16U i;            /* will index into CRC lookup */

    /* pass through message buffer */
    while (buffer_length--)
    {
        i = crc_hi ^ *buffer++; /* calculate the CRC  */
        crc_hi = crc_lo ^ table_crc_hi[i];
        crc_lo = table_crc_lo[i];
    }
    return (crc_hi << 8 | crc_lo);
    // return (crc_lo << 8 | crc_hi);
}

void getTimeString(char *temp)
{
    struct tm *ptm;
    long ts;
    int y, m, d, h, n, s;
    char str[50] = {0};
    char strTemp[10] = {0};

    ts = time(NULL);
    ptm = localtime(&ts);
    y = ptm->tm_year + 1900; //年
    m = ptm->tm_mon + 1;     //月
    d = ptm->tm_mday;        //日
    h = ptm->tm_hour;        //时
    n = ptm->tm_min;         //分
    s = ptm->tm_sec;         //秒
    sprintf(strTemp, "%d", y);
    strcat(str, strTemp);
    strcat(str, "-");
    if (m < 10)
        strcat(str, "0");
    sprintf(strTemp, "%d", m);
    strcat(str, strTemp);
    strcat(str, "-");
    if (d < 10)
        strcat(str, "0");
    sprintf(strTemp, "%d", d);
    strcat(str, strTemp);
    strcat(str, " ");
    if (h < 10)
        strcat(str, "0");
    sprintf(strTemp, "%d", h);
    strcat(str, strTemp);
    strcat(str, ":");
    if (n < 10)
        strcat(str, "0");
    sprintf(strTemp, "%d", n);
    strcat(str, strTemp);
    strcat(str, ":");
    if (s < 10)
        strcat(str, "0");
    sprintf(strTemp, "%d", s);
    strcat(str, strTemp);
    strcpy(temp, str);
}
